package com.zfei.gfb.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.time.Duration;
import java.util.List;

/**
 * @author fgh
 */
public class RedisLogic {

    private static final Logger logger = LoggerFactory.getLogger(RedisLogic.class);

    private StringRedisTemplate redis;

    public RedisLogic(RedisConnectionFactory factory) {
        this.redis = new StringRedisTemplate(factory);
    }

    public StringRedisTemplate getRedis() {
        return redis;
    }

    public ValueOperations<String, String> opsForValue() {
        return this.getRedis().opsForValue();
    }

    public void set(String key, Object value) {
        this.opsForValue().set(key, String.valueOf(value));
    }

    public void set(String key, Object value, Duration timeout) {
        this.opsForValue().set(key, String.valueOf(value), timeout);
    }

    public String get(String key) {
        return this.opsForValue().get(key);
    }

    public int getInt(String key) {
        String value = get(key);
        return value != null ? Integer.parseInt(value) : 0;
    }

    public long getLong(String key) {
        String value = get(key);
        return value != null ? Long.parseLong(value) : 0L;
    }

    public long incr(String key, long value, Duration timeout) {
        List<Object> pipelined = this.redis.executePipelined((RedisCallback<Object>) connection -> {
            StringRedisConnection conn = (StringRedisConnection) connection;
            if (value < 0) {
                conn.decrBy(key, -value);
            } else {
                conn.incrBy(key, value);
            }
            conn.expire(key, timeout.getSeconds());
            return null;
        });
        if (pipelined != null && pipelined.size() > 0) {
            return Long.parseLong(pipelined.get(0).toString());
        }
        return -1L;
    }

    public double zIncr(String key, double value, String member, Duration timeout) {
        List<Object> pipelined = this.redis.executePipelined((RedisCallback<Object>) connection -> {
            StringRedisConnection conn = (StringRedisConnection) connection;
            conn.zIncrBy(key, value, member);
            conn.expire(key, timeout.getSeconds());
            return null;
        });
        if (pipelined != null && pipelined.size() > 0) {
            return Double.parseDouble(pipelined.get(0).toString());
        }
        return -1L;
    }
}
